﻿using ColiyerWpfControl.Gis.Entity;
using ColiyerWpfControl.Gis.GeoLayer;
using ColiyerWpfControl.Gis.ViewModel;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.UI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

namespace ColiyerWpfControl.Gis.MapView
{
    public partial class SimpleMapViewControl : UserControl
    {

        private const double viewScale = 1155581.108577;
        private const double previewScale = 1155581.108577;

        public static Symbol LON_LAT_GRID_LINE_SYMBOL = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, System.Drawing.Color.FromArgb(0x55, 0x88, 0x88, 0x88), 1);
        public static Symbol LON_LAT_TEXT_LINE_SYMBOL = new TextSymbol()
        {
            Color = System.Drawing.Color.FromArgb(0x99, 0xff, 0xff, 0xff),
            Size = 9,
            HaloWidth = 0,
            OffsetY = 20,
        };
        Dictionary<string, GraphicsOverlay> _overlayDic = new Dictionary<string, GraphicsOverlay>();

        public ObservableCollection<GraphicsOverlay> Overlays { get; set; }=new ObservableCollection<GraphicsOverlay>();

        public ObservableCollection<TrackEntity> TrackItemSource
        {
            get { return (ObservableCollection<TrackEntity>)GetValue(TrackItemSourceProperty); }
            set { SetValue(TrackItemSourceProperty, value); }
        }

        public static readonly DependencyProperty TrackItemSourceProperty =
            DependencyProperty.Register("TrackItemSource", typeof(ObservableCollection<TrackEntity>), typeof(SimpleMapViewControl), new PropertyMetadata(null, OnTrackItemSourceChanged));

        public Layer GeoLayer
        {
            get { return (Layer)GetValue(GeoLayerProperty); }
            set { SetValue(GeoLayerProperty, value); }
        }

        public static readonly DependencyProperty GeoLayerProperty =
            DependencyProperty.Register("GeoLayer", typeof(Layer), typeof(SimpleMapViewControl),
                new PropertyMetadata(null, OnGeoLayerChanged));

        private static void OnGeoLayerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (SimpleMapViewControl)d;
            if (control.MapViewControl.Map==null)
            {
                control.MapViewControl.Map = new Map() {
                    MinScale = 73957190.948944,
                };
            }
            if (e.NewValue is Layer layer)
            {
                control.MapViewControl.Map.OperationalLayers.Add(layer);
            }
            
        }



        public TrackEntity SelectItem
        {
            get { return (TrackEntity)GetValue(SelectItemProperty); }
            set { SetValue(SelectItemProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectItem.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectItemProperty =
            DependencyProperty.Register("SelectItem", typeof(TrackEntity), typeof(SimpleMapViewControl), 
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,OnSelectItemChanged));

        private static void OnSelectItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SimpleMapViewControl control = (SimpleMapViewControl)d;
            control.SetSelectItem((TrackEntity)e.NewValue);
        }

        private async void SetSelectItem(TrackEntity newValue)
        {
            if (newValue!=null)
            {
                SpatioLoc ls = newValue.Loc.Last();
                MapPoint loc = new MapPoint(ls.Lon, ls.Lat, SpatialReferences.Wgs84);
                await MapViewControl.SetViewpointCenterAsync(loc);
            }
        }

        public SimpleMapViewControl()
        {
            InitializeComponent();
            InitOverlayer();
        }

        private void InitOverlayer()
        {
            MapViewControl.Grid.SetLineSymbol(0, LON_LAT_GRID_LINE_SYMBOL);
            MapViewControl.Grid.SetTextSymbol(0, LON_LAT_TEXT_LINE_SYMBOL);
            
        }

        private static void OnTrackItemSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as SimpleMapViewControl;

            // 移除旧集合的事件订阅
            if (e.OldValue is ObservableCollection<TrackEntity> oldCollection)
            {
                oldCollection.CollectionChanged -= control.TrackItemSource_CollectionChanged;
            }

            // 添加新集合的事件订阅
            if (e.NewValue is ObservableCollection<TrackEntity> newCollection)
            {
                newCollection.CollectionChanged += control.TrackItemSource_CollectionChanged;
            }

            // 初始化更新
            control?.UpdateTracks(null);
        }
        private void TrackItemSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            UpdateTracks(e);
        }
        private void UpdateTracks(NotifyCollectionChangedEventArgs e)
        {
            if (TrackItemSource == null || !TrackItemSource.Any() || e == null) {
                Clear();
                return;
            }


            // 根据集合变化的类型进行处理
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    // 新增轨迹
                    foreach (TrackEntity newTrack in e.NewItems)
                    {
                        AddTrackGraphics(newTrack);
                    }
                    break;

                case NotifyCollectionChangedAction.Remove:
                    // 删除轨迹
                    foreach (TrackEntity oldTrack in e.OldItems)
                    {
                        RemoveTrackGraphics(oldTrack.Series);
                    }
                    break;

                case NotifyCollectionChangedAction.Replace:
                    // 替换轨迹
                    foreach (TrackEntity oldTrack in e.OldItems)
                    {
                        RemoveTrackGraphics(oldTrack.Series);
                    }
                    foreach (TrackEntity newTrack in e.NewItems)
                    {
                        AddTrackGraphics(newTrack);
                    }
                    break;

                case NotifyCollectionChangedAction.Reset:
                    // 清空轨迹
                    ClearAllTracks();
                    break;

                case NotifyCollectionChangedAction.Move:
                    // 不处理移动
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
        private void Clear()
        {
            foreach (KeyValuePair<string, GraphicsOverlay> item in _overlayDic)
            {
                item.Value.Graphics.Clear();
            }
        }
        private void AddTrackGraphics(TrackEntity track)
        {
            if (track == null) return;

            var overlay = GetOverlayer(track.Series);

            // 创建轨迹线的几何对象
            IEnumerable<MapPoint> points = track.Loc.Where(x=>x.Lon!=0).Select(loc => new MapPoint(loc.Lon, loc.Lat, SpatialReferences.Wgs84));
            Polyline polyline = new Polyline(points);

            // 创建线样式
            SimpleLineSymbol lineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, track.MarkerColor, 1);

            // 创建图形并添加到图层
            Graphic lineGraphic = new Graphic(polyline, lineSymbol);
            overlay.Graphics.Add(lineGraphic);

            // 为每个点添加标记（可选）
            foreach (MapPoint point in points)
            {
                Graphic pointGraphic = new Graphic(point, new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, track.MarkerColor, 3));
                overlay.Graphics.Add(pointGraphic);
            }
        }

        private void RemoveTrackGraphics(string series)
        {
            if (string.IsNullOrEmpty(series)) return;

            if (_overlayDic.TryGetValue(series, out var overlay))
            {
                // 删除对应图层中的所有图形
                overlay.Graphics.Clear();
                MapViewControl.GraphicsOverlays.Remove(overlay);
                Overlays.Remove(overlay);
                _overlayDic.Remove(series);
            }
        }

        private void ClearAllTracks()
        {
            foreach (var overlay in _overlayDic.Values)
            {
                overlay.Graphics.Clear();
                MapViewControl.GraphicsOverlays.Remove(overlay);
            }
            _overlayDic.Clear();
            Overlays.Clear();
        }

        private GraphicsOverlay GetOverlayer(string tag)
        {
            if(string.IsNullOrEmpty(tag))
                throw new ArgumentNullException(nameof(tag));
            if (!_overlayDic.TryGetValue(tag,out var overlayer))
            {
                overlayer = new GraphicsOverlay();
                overlayer.Id = tag;
                MapViewControl.GraphicsOverlays.Add(overlayer);
                Overlays.Add(overlayer);
                _overlayDic.Add(tag, overlayer);
            }
            return overlayer;
        }
    }
}
